using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace TPXSDK.NET.Link;

/// <inheritdoc />
/// <summary>
/// TCP Client网络通讯适配器 [支持多网卡结构]
/// TCPC:本机IP:本机端口:目标IP:目标端口号
/// </summary>
public class TcpClientAdapter : CommAdapter
{
    #region 成员变量
    private readonly IPEndPoint? _destEp;
    private readonly IPEndPoint? _localEp;
    private Thread? _socketRcvThread;
    private volatile bool _isRunning;
    private readonly byte[] _rcvData = new byte[4096];
    private readonly List<object> _refObjs = [];
    private readonly object _locker = new();
	private TcpClient? _tcpClient;
    #endregion

    public TcpClientAdapter(string strDesc)
    {
        // 分析字符串并初始化TcpClient连接
        var strPara = strDesc.Split(':');
        if (strPara.Length != 5)
        {
            throw new Exception($"Invalid TcpClientAdapter{strDesc}");
        }
        var srcPort = Convert.ToInt32(strPara[2]);
        _localEp = new IPEndPoint(IPAddress.Parse(strPara[1]), srcPort);
        var destIp = IPAddress.Parse(strPara[3]);
        var destPort = Convert.ToInt32(strPara[4]);
        _destEp = new IPEndPoint(destIp, destPort);
    }

    /// <summary>
    /// Releases unmanaged and - optionally - managed resources
    /// </summary>
    public virtual void Dispose()
    {

    }

    /// <summary>
    /// 打开通讯适配器
    /// </summary>
    public override bool Open()
    {
        if (_isRunning || null == _destEp || null == _localEp) return true;

        try
        {
            _tcpClient?.Close();
            _tcpClient = new TcpClient(_localEp);
            _tcpClient.Connect(_destEp);

            if (_tcpClient.Connected)
            {
                _socketRcvThread = new Thread(SocketReceiveHandle)
                {
                    IsBackground = true
                };                
                _isRunning = true;
                _socketRcvThread.Start();

                return true;
            }

            Trace.TraceError("TCPClient Connect Timeout");
            _tcpClient.Dispose();            
            return false;
        }
        catch (Exception exp)
        {
            Trace.TraceError($"TCP:{exp}");
            NotifyCommError($"{exp}");
			_tcpClient?.Dispose();
            return false;
        }
    }

    /// <summary>
    /// 数据接收回调处理函数
    /// </summary>
    private void SocketReceiveHandle()
    {
        var ns = _tcpClient?.GetStream();
        
        while (_isRunning)
        {
            if (_tcpClient == null || null == _destEp || null == ns)
            {
                _isRunning = false;
                break;
            }

            try
            {                
                var len = ns.Read(_rcvData, 0, _rcvData.Length);
                if (len > 0)
                {
                    NotifyDataRcv(_rcvData, len);
                }
            }
            catch (Exception exp)
            {
                _isRunning = false;//Stop Socket Recv Thread
                Trace.TraceError(exp.ToString());
                break;
            }
        }

        // 关闭处理
        if (null != _tcpClient)
        {
            ns?.Flush();
            ns?.Close();
            _tcpClient.Close();
            _tcpClient.Dispose();
            _tcpClient = null;
            Trace.WriteLine("TcpClient Closed");
        }        
    }

    /// <inheritdoc />
    /// <summary>
    /// 关闭适配器
    /// </summary>
    public override void Close()
    {
        _isRunning = false;
    }

    /// <summary>
    /// 添加引用对象，返回当前引用对象个数
    /// </summary>
    public override int AddRefObj(object user)
    {
        if (!_refObjs.Contains(user))
        {
            _refObjs.Add(user);
        }
        return _refObjs.Count;
    }

    /// <summary>
    /// 删除引用对象，返回当前引用对象个数，当值为零时可以安全调用 Close()
    /// </summary>
    public override int DelRefObj(object user)
    {
        _refObjs.Remove(user);
        return _refObjs.Count;
    }

    public override void Write(string text)
    {
        if (!_isRunning || null == _destEp)
        {
            return;
        }

        var bytes = Encoding.ASCII.GetBytes(text);
        lock (_locker)
        {
            _tcpClient?.Client.SendTo(bytes, bytes.Length, SocketFlags.None, _destEp);
        }
    }

    public override void Write(byte[] buffer, int offset, int len)
    {
        if (!_isRunning || null == _destEp)
        {
            return;
        }

        lock (_locker)
        {
            _tcpClient?.Client.SendTo(buffer, offset, len, SocketFlags.None, _destEp);
        }
    }

    public override void Write(byte[] buffer)
    {
        if (!_isRunning || null == _destEp)
        {
            return;
        }

        lock (_locker)
        {
            _tcpClient?.Client.SendTo(buffer, buffer.Length, SocketFlags.None, _destEp);
        }
    }

    /// <summary>
    /// 判断端口是否打开
    /// </summary>
    public override bool IsOpened
    {
        get { return _isRunning; }
    }
}//end TcpClientAdapter
